/**
 * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
 */
package com.ld.shieldsb.common.core.collections;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;

import com.ld.shieldsb.common.core.reflect.FunctionUtil.Property;

/**
 * 
 * List工具类
 * 
 * @ClassName ListUtils
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2018年11月15日 下午6:34:58
 *
 */
public class ListUtils extends org.apache.commons.collections.ListUtils {

    public static <E> ArrayList<E> newArrayList() {
        return new ArrayList<>();
    }

    @SafeVarargs
    public static <E> ArrayList<E> newArrayList(E... elements) {
        ArrayList<E> list = new ArrayList<>(elements.length);
        Collections.addAll(list, elements);
        return list;
    }

    public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
        return (elements instanceof Collection) ? new ArrayList<>(cast(elements)) : newArrayList(elements.iterator());
    }

    public static <E> ArrayList<E> newArrayList(Iterator<? extends E> elements) {
        ArrayList<E> list = newArrayList();
        addAll(list, elements);
        return list;
    }

    public static <E> LinkedList<E> newLinkedList() {
        return new LinkedList<>();
    }

    public static <E> LinkedList<E> newLinkedList(Iterable<? extends E> elements) {
        LinkedList<E> list = newLinkedList();
        addAll(list, elements);
        return list;
    }

    public static <E> CopyOnWriteArrayList<E> newCopyOnWriteArrayList() {
        return new CopyOnWriteArrayList<>();
    }

    public static <E> CopyOnWriteArrayList<E> newCopyOnWriteArrayList(Iterable<? extends E> elements) {
        Collection<? extends E> elementsCollection = (elements instanceof Collection) ? cast(elements) : newArrayList(elements);
        return new CopyOnWriteArrayList<>(elementsCollection);
    }

    private static <T> Collection<T> cast(Iterable<T> iterable) {
        return (Collection<T>) iterable;
    }

    private static <T> boolean addAll(Collection<T> addTo, Iterator<? extends T> iterator) {
        boolean wasModified = false;
        while (iterator.hasNext()) {
            wasModified |= addTo.add(iterator.next());
        }
        return wasModified;
    }

    public static <T> boolean addAll(Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
        if (elementsToAdd instanceof Collection) {
            Collection<? extends T> c = cast(elementsToAdd);
            return addTo.addAll(c);
        }
        return addAll(addTo, elementsToAdd.iterator());
    }

    /**
     * 转换Collection所有元素(通过toString())为String, 中间以 separator分隔。
     */
    public static <T> String convertToString(final Collection<T> collection, final String separator) {
        return StringUtils.join(collection, separator);
    }

    /**
     * 转换Collection所有元素(通过toString())为String, 每个元素的前面加入prefix，后面加入postfix，如<div>mymessage</div>。
     */
    public static <T> String convertToString(final Collection<T> collection, final String prefix, final String postfix) {
        StringBuilder builder = new StringBuilder();
        for (Object o : collection) {
            builder.append(prefix).append(o).append(postfix);
        }
        return builder.toString();
    }

    /**
     * 判断是否为空.
     */
    public static <T> boolean isEmpty(Collection<T> collection) {
        return (collection == null || collection.isEmpty());
    }

    /**
     * 判断是否为不为空.
     */
    public static <T> boolean isNotEmpty(Collection<T> collection) {
        return !(isEmpty(collection));
    }

    /**
     * 取得Collection的第一个元素，如果collection为空返回null.
     */
    public static <T> T getFirst(Collection<T> collection) {
        if (isEmpty(collection)) {
            return null;
        }
        return collection.iterator().next();
    }

    /**
     * 获取Collection的最后一个元素 ，如果collection为空返回null.
     */
    public static <T> T getLast(Collection<T> collection) {
        if (isEmpty(collection)) {
            return null;
        }
        // 当类型为List时，直接取得最后一个元素 。
        if (collection instanceof List) {
            List<T> list = (List<T>) collection;
            return list.get(list.size() - 1);
        }
        // 其他类型通过iterator滚动到最后一个元素.
        Iterator<T> iterator = collection.iterator();
        while (true) {
            T current = iterator.next();
            if (!iterator.hasNext()) {
                return current;
            }
        }
    }

    /**
     * 返回a+b的新List.
     */
    public static <T> List<T> union(final Collection<T> a, final Collection<T> b) {
        List<T> result = new ArrayList<>(a);
        result.addAll(b);
        return result;
    }

    /**
     * 返回a-b的新List.
     */
    public static <T> List<T> subtract(final Collection<T> a, final Collection<T> b) {
        List<T> list = new ArrayList<>(a);
        for (T element : b) {
            list.remove(element);
        }
        return list;
    }

    /**
     * 返回a与b的交集的新List.
     */
    public static <T> List<T> intersection(Collection<T> a, Collection<T> b) {
        List<T> list = new ArrayList<>();
        for (T element : a) {
            if (b.contains(element)) {
                list.add(element);
            }
        }
        return list;
    }

    /**
     * 获取List的副本
     * 
     * @Title getCopyList
     * @author 吕凯
     * @date 2019年2月23日 下午1:34:26
     * @param a
     * @return List<T>
     */
    public static <T> List<T> getCopyList(Collection<T> a) {
        List<T> copyList = new ArrayList<>();
        copyList.addAll(a);
        return copyList;
    }

    /**
     * 判断列表中是否存在值
     * 
     * @Title hasValue
     * @author 吕凯
     * @date 2019年8月31日 上午9:11:37
     * @param model
     * @param colls
     * @return boolean
     */
    public static <T> boolean hasValue(Collection<T> colls, final T model) {
        return colls.stream().anyMatch(p -> p.equals(model));
    }

    /**
     * 
     * list中2个字段转位map,如果存在重复的，保留最后一个
     * 
     * @Title listField2Map
     * @author 吕凯
     * @date 2021年5月18日 上午11:14:55
     * @param <T>
     * @param <K>
     * @param <U>
     * @param list
     * @param property
     * @param property2
     * @return Map<K,U>
     */
    public static <T, K, U> Map<K, U> listField2Map(List<T> list, Property<T, K> property, Property<T, U> property2) {
        return listField2Map(list, property, property2, false);
    }

    /**
     * 
     * list中2个字段转位map
     * 
     * @Title listField2Map
     * @author 吕凯
     * @date 2021年5月18日 上午11:12:57
     * @param list
     *            list
     * @param property
     *            key
     * @param property2
     *            value
     * @param duplicateKeySaveFirst
     *            如果存在重复的，是否保留第一个
     * @return Map<K,U>
     */
    public static <T, K, U> Map<K, U> listField2Map(List<T> list, Property<T, K> property, Property<T, U> property2,
            Boolean duplicateKeySaveFirst) {
        // 如果有重复的key,则保留key1,舍弃key2
        return list.stream().collect(Collectors.toMap(property, property2, (k1, k2) -> duplicateKeySaveFirst ? k1 : k2));
    }

    /**
     * list中一个字段作为key，将list中对象作为value转，map,如果存在重复的，保留最后一个
     * 
     * @Title listField2Map
     * @author 吕凯
     * @date 2021年5月21日 下午6:00:55
     * @param <T>
     * @param <K>
     * @param list
     * @param keyProperty
     * @return Map<K,T>
     */
    public static <T, K> Map<K, T> listField2Map(List<T> list, Property<T, K> keyProperty) {
        // 如果有重复的key,则保留key1,舍弃key2
        return listField2Map(list, keyProperty, false);
    }

    /**
     * list中一个字段作为key，将list中对象作为value转，map
     * 
     * @Title listField2Map
     * @author 吕凯
     * @date 2021年5月21日 下午5:58:42
     * @param list
     *            集合
     * @param keyProperty
     *            作为key 的属性
     * @param duplicateKeySaveFirst
     *            如果存在重复的，是否保留第一个
     * @return Map<K,T>
     */
    public static <T, K> Map<K, T> listField2Map(List<T> list, Property<T, K> keyProperty, Boolean duplicateKeySaveFirst) {
        // 如果有重复的key,则保留key1,舍弃key2
        return list.stream().collect(Collectors.toMap(keyProperty, account -> account, (k1, k2) -> duplicateKeySaveFirst ? k1 : k2));
    }

    /**
     * 将List按每组固定数拆分，最后一组可能不够这个数目
     * 
     * @Title splitList2Group
     * @author 吕凯
     * @date 2021年12月7日 上午11:19:12
     * @param <T>
     * @param list
     * @param groupSize
     * @return List<List<T>>
     */
    public static <T> List<List<T>> splitList2Group(List<T> list, int groupSize) {
        List<List<T>> resultList = new ArrayList<>();
        int groupCount = (list.size() - 1) / groupSize + 1;
        for (int i = 0; i < groupCount; i++) {
            List<T> dmlsBatch;

            if (i == groupCount - 1) { // 最后没有数据则剩余几条就装几条
                dmlsBatch = list.subList(groupSize * i, list.size());
            } else {

                dmlsBatch = list.subList(groupSize * i, groupSize * (i + 1));
            }
            resultList.add(dmlsBatch);
        }
        return resultList;
    }

}